perm filename FTP.MAC[11,HE]1 blob
sn#556071 filedate 1981-01-14 generic text, type C, neo UTF8
COMMENT ⊗ VALID 00010 PAGES
C REC PAGE DESCRIPTION
C00001 00001
C00002 00002 .TITLE File Transfer Program
C00007 00003 Auxiliary routines to parse filenames: FPAR11 & FPAR10
C00013 00004 Some more auxiliary routines: SETF11, SETF10, FCOPY, SKIPB
C00017 00005 I/O auxiliary routines: GETLIN & OUTNUM
C00019 00006 Program initialization
C00022 00007 Command loop
C00025 00008 Store 10file ← 11file
C00029 00009 Get 11file ← 10file
C00033 00010 Set alias ppn for 10 & Exit
C00035 ENDMK
C⊗;
.TITLE File Transfer Program
.MCALL ALUN$S,GLUN$S,QIOW$S,EXIT$S,GREG$S,MRKT$S,WTSE$S
.MCALL FDBDF$,FDAT$A,FDRC$A,FDBK$A,FDOP$A,FINIT$,FSRSZ$
.MCALL OPEN$R,OPEN$W,CLOSE$,READ$,WRITE$
.MCALL WAIT$
;need mcall for pausing 1/60 sec or thereabouts
; MRKT$S #1,#1,#1 ;efn,tmg,tnt
; MRKT$S #1,#2,#1 ;Wait two ticks
; BCS 1$ ;If it isn't accepted don't bother waiting
; WTSE$S #1
; 1$:
;?? what if file exactly fits last block? what are values for F.EFBK & F.FFBY??
.BLKW 100 ;Make some stack space
SPSTRT:
REGBUF: .BLKW 3 ;To stick region info into
RDSTS: .WORD 0 ;Read status block
RDCNT: .WORD 0
TTYBUF: .BLKB 80. ;For reading commands
WRSTS: .WORD 0,0 ;Write status block
STATBF: .BYTE TC.SCP ;Ask if CRT
TALK11: .BYTE 0
ECHO: .BYTE TC.NEC ;Set /ECHO=TT10: or /NOECHO=TT10:
ECHOP: .BYTE 1
FLBUF: .BYTE TC.TBF,0 ;Also flush type-ahead buffer
SLAVE: .BYTE TC.SLV ;Set terminal = slave
SLAVEP: .BYTE 0
IOSTAT: .WORD 0,0 ;Status for disk ops
F1: .WORD 0,0 ;Pointer/length pairs
F2: .WORD 0,0
FNAM11: .WORD 0,0
FEXT11: .WORD 0,0
FVER11: .WORD 0,0
FNAM10: .WORD 0,0
FEXT10: .WORD 0,0
PPN10: .WORD 0,0
ALIAS: .WORD DEFPPN,7 ;Default ppn for 10
LUN10: .WORD 1 ;Logical unit number for tty link to 10
NUMBUF: .BLKB 12.
BUFPTR: .WORD 0
FILDON: .WORD 0 ;Contains first free byte address for last buffer
CMD: .WORD 0
FDB: FDBDF$ ;Make up the disk header info
; FDAT$A R.FIX,,512.,-120.
; FDRC$A FD.RWM
; FDBK$A BUFFER,512.,,2,IOSTAT
; FDOP$A 2,DATSET
FSRSZ$ 1
DBUF: .BLKW 256. ;Disk block buffer
DATSET:
DEVCNT: .WORD 0
DEVNAM: .WORD 0
UICCNT: .WORD 0
UICNAM: .WORD 0
FILCNT: .WORD 0
FILNAM: .WORD FILBUF
DEV: .ASCII / /
SYSDEV: .ASCII /SY:/
OKMES: .ASCII /OK/
OKSIZ = .-OKMES
BADDEV: .ASCII /NO SUCH DEVICE/
BDEVSZ = .-BADDEV
BADFIL: .ASCII /CAN'T OPEN FILE/
BFILSZ = .-BADFIL
HIMES: .ASCII <15><12>/10-11 FTP Program/<15><12><12>
.ASCII /G to get a file from the 10/<15><12>
.ASCII /S to store a file on the 10/<15><12>
.ASCII /A to set an alias on the 10 {default= [11,HE]}/<15><12>
.ASCII /X to exit/<15><12><12>
HISIZ = .-HIMES
LOGMES: .ASCII <15>/L 11.HE/<15>
LOGSIZ = .-LOGMES
RUNMES: .ASCII /R 11FTP/<15>
RUNSIZ = .-RUNMES
BYEMES: .ASCII /X /<15><15>/K/<15>
BYESIZ = .-BYEMES
DEFPPN: .ASCII /[11,HE] /
DEFVER: .ASCII /;0/
PROMPT: .ASCII <15><12>/*/
PRSIZ = .-PROMPT
CMDMES: .ASCII /S /
FILBUF: .BLKB 30.
ABTMES: .ASCII <12>/Aborted by 10 /
ABTSIZ = .-ABTMES
UNKMES: .ASCII /Unknown command/
UNKSIZ = .-UNKMES
.EVEN
;Auxiliary routines to parse filenames: FPAR11 & FPAR10
; called with R0 pointing to string to parse
FPAR11: MOV (R0)+,R1 ;R1 ← chars to parse
MOV (R0),R4 ;R4 ← char count
CLR DEVCNT ;Clear out old values
CLR UICCNT
CLR FNAM11+2
CLR FEXT11+2
MOV #DEFVER,FVER11 ;Set default version # to ";0"
MOV #2,FVER11+2
CMPB (R1),#"[ ;UIC?
BEQ UICPAR ;Go parse UIC, no device given
CMPB 1(R1),#": ;See if we have a device
BEQ DEVPAR
CMPB 2(R1),#":
BEQ DEVPAR
CMPB 3(R1),#":
BEQ DEVPAR
BR PFNM11 ;No device or UIC given - get filename
DEVPAR: MOV R1,DEVNAM ;Point data set at device name
MOVB (R1)+,DEV ;Store first char of device name
CLRB DEV+1 ;In case no second char
CLR R3 ;Unit # of device (default = 0)
1$: INC DEVCNT
CMPB (R1),#": ;Scan til ":"
BEQ 3$ ; Done
CMPB (R1),#"A ;Alpha?
BMI 2$ ; No - < "A"
MOVB (R1)+,DEV+1 ;Store second char of device name
BR 1$
2$: MOVB (R1)+,R3 ;Get Unit # in R3
SUB #60,R3 ;Convert ASCII to # (-"0")
BR 1$
3$: INC R1
INC DEVCNT
SUB DEVCNT,R4 ;Update char count
ALUN$S #2,DEV,R3 ;LUN 2 is device
BCC UICPAR
QIOW$S #IO.WLB,#1,#1,,#WRSTS,,<#BADDEV,#BDEVSZ,#40> ;Abort if bad dev
BCC 4$
IOT ;Punt if error
4$: SEC ;Indicate an error
RTS PC ; & Return
UICPAR: CMPB (R1),#"[ ;UIC?
BNE PFNM11 ;Go parse filename, no UIC given
MOV R1,UICNAM ;Point to start of UIC
1$: INC UICCNT
CMPB (R1)+,#"] ;Scan to closing "]"
BNE 1$
SUB UICCNT,R4 ;Update count of characters left
PFNM11: TST R4 ;Check more to parse
BEQ 6$ ; No - all done here (almost)
MOV R1,FNAM11 ;Point to start of filename
1$: CMPB (R1),#". ;Search til "."
BEQ 2$
CMPB (R1),#"; ; or ";"
BEQ 2$
INC R1 ;Point to next char
DEC R4 ;Update chars left
BGT 1$ ; & keep going if any left
2$: MOV R1,FNAM11+2
SUB FNAM11,FNAM11+2 ;Length of file name
CMPB (R1),#". ;Extension present
BNE 5$ ; No
MOV R1,FEXT11 ;Point to start of file extension
3$: CMPB (R1),#"; ;Search til ";"
BEQ 4$
INC R1 ;Point to next char
DEC R4 ;Update chars left
BGT 3$ ; & keep going if any left
4$: MOV R1,FEXT11+2
SUB FEXT11,FEXT11+2 ;Length of file extension
5$: CMPB (R1),#"; ;Version number present?
BNE 6$ ; No
MOV R1,FVER11 ; Yes - point to start of version #
MOV R4,FVER11+2 ; & indicate it's length
6$: TST DEVCNT ;Was a device specified?
BNE 7$ ; Yes - all done
MOV #SYSDEV,DEVNAM ; No - use SY: as default
MOV #3,DEVCNT
ALUN$S #2,#"SY,#0 ;LUN 2 is SY:
7$: CLC ;Indicate success
RTS PC ;All done here
FPAR10: MOV (R0)+,R1 ;R1 ← chars to parse
MOV (R0),R4 ;R4 ← char count
CLR FNAM10+2 ;Zero old values
CLR FEXT10+2
MOV ALIAS,PPN10 ;Assume alias ppn
MOV ALIAS+2,PPN10+2
TST R4 ;Check if anything to parse
BEQ 8$ ; No - all done here
MOV R1,FNAM10 ;Point to start of filename
1$: CMPB (R1),#". ;Search til "."
BEQ 2$
CMPB (R1),#"[ ; or "["
BEQ 2$
INC R1 ;Point to next char
DEC R4 ;Update chars left
BGT 1$ ; & keep going if any left
2$: MOV R1,FNAM10+2
SUB FNAM10,FNAM10+2 ;Length of file name
CMPB (R1),#". ;Extension present
BNE 5$ ; No
MOV R1,FEXT10 ;Point to start of file extension
3$: CMPB (R1),#"[ ;Search til "["
BEQ 4$
INC R1 ;Point to next char
DEC R4 ;Update chars left
BGT 3$ ; & keep going if any left
4$: MOV R1,FEXT10+2
SUB FEXT10,FEXT10+2 ;Length of file extension
5$: CMPB (R1),#"[ ;PPN?
BNE 8$ ; No - all done
MOV R1,PPN10 ;Point to start of ppn
6$: DEC R4 ;Update char count
BMI 7$ ;Quit if no more chars
CMPB (R1)+,#"] ;Scan to closing "]"
BNE 6$
7$: MOV R1,PPN10+2
SUB PPN10,PPN10+2 ;Length of ppn
8$: RTS PC ;All done - return
;Some more auxiliary routines: SETF11, SETF10, FCOPY, SKIPB
SETF11: MOV #FILBUF,R2
MOV #30,R0
1$: CLRB (R2)+ ;Zero out old file name
SOB R0,1$
MOV #FILBUF,R2 ;Now build up new one
CLR R3
MOV #FNAM11,R0 ;Copy file name
JSR PC,FCOPY
MOV #FEXT11,R0 ;Copy file extension
JSR PC,FCOPY
MOV #FVER11,R0 ;Copy file version number
JSR PC,FCOPY
MOV R3,FILCNT ;Set filename char count
RTS PC
SETF10: MOV #FILBUF,R2
MOV #30,R0
1$: CLRB (R2)+ ;Zero out old file name
SOB R0,1$
MOV #FILBUF,R2 ;Now build up new one
CLR R3
MOV #FNAM10,R0 ;Copy file name
JSR PC,FCOPY
MOV #FEXT10,R0 ;Copy file extension
JSR PC,FCOPY
MOV #PPN10,R0 ;Copy ppn
JSR PC,FCOPY
MOVB #15,(R2)+ ;Append a cr
ADD #3,R3 ;Fix up char count to include command & cr
QIOW$S #IO.WLB,#3,#1,,#WRSTS,,<#CMDMES,R3,#0> ;Tell 10 file to rd/wrt
BCC 2$
IOT ;Punt if error
2$: MOV #3,R3
JSR PC,GETLIN ;Ignore echo
TST R4
BEQ 2$ ;Repeat if null line
3$: MOV #3,R3
JSR PC,GETLIN ;Get 10's reply
TST R4
BEQ 3$ ;Repeat if null line
CMPB (R1),#"O ;Is everything okay?
BNE 4$ ; No - complain
CMPB 1(R1),#"K
BEQ 5$ ; Yes - go do the transfer
4$: MOV R1,-(SP) ;Save error string
MOV R4,-(SP)
QIOW$S #IO.WLB,#1,#1,,#WRSTS,,<#ABTMES,#ABTSIZ,#0> ;Say we're aborting
MOV (SP)+,R4
MOV (SP)+,R1
QIOW$S #IO.WLB,#1,#1,,#WRSTS,,<R1,R4,#0> ; & tell why
SEC ;Indicate abort & return
RTS PC
5$: CLC ;Indicate all's well & return
RTS PC
FCOPY: MOV (R0)+,R1 ;R1 ← String to copy
MOV (R0),R4 ;R4 ← char count for string
BEQ 2$ ;If null string all done
ADD R4,R3 ;Update current string length
1$: MOVB (R1)+,(R2)+ ;Copy chars
SOB R4,1$
2$: RTS PC ;Done
SKIPB: CMPB (R1),#40 ;A blank?
BNE 1$ ; No - all done
INC R1
DEC R4 ;Update char count
BGT SKIPB ; & keep going if more
1$: RTS PC ;Done
;I/O auxiliary routines: GETLIN & OUTNUM
GETLIN: MOV #TTYBUF,R1
MOV #40,R0
1$: CLR (R1)+ ;Zero command line buffer
SOB R0,1$
QIOW$S #IO.RLB,R3,#1,,#RDSTS,,<#TTYBUF,#80.> ;Read in a line
BCC 2$
IOT ;Punt if error
2$: MOV #TTYBUF,R1
3$: CMPB (R1),#12 ;Skip over linefeeds
BNE 4$
INC R1
DEC RDCNT ;Update read count
BPL 3$
4$: RTS PC
;Auxiliary routine to print out the octal number in R1
OUTNUM: MOV R0,-(SP) ;We need some free registers
MOV R1,-(SP)
MOV R2,-(SP)
MOV R3,-(SP)
MOV #NUMBUF,R2 ;Where we'll stick the result
CLR R0
MOV #6,R3 ;6 digits to print
ASHC #1,R0 ;Get high order digit
1$: TST R0 ;Don't print leading zeros
BNE 2$ ;Found highest order non-zero digit
ASHC #3,R0 ;Try next
SOB R3,1$
INC R3
2$: ADD #60,R0 ;Convert to ASCII
MOVB R0,(R2)+ ;Stick it in buffer
CLR R0
ASHC #3,R0 ;Move on to next digit
SOB R3,2$ ;Do them all
SUB #NUMBUF,R2 ;Get character count for writing
QIOW$S #IO.WLB,LUN10,#1,,#WRSTS,,<#NUMBUF,R2,#40> ;Type it out to 10
BCC 3$
IOT ;Punt if error
3$: MOV (SP)+,R3 ;Restore registers
MOV (SP)+,R2
MOV (SP)+,R1
MOV (SP)+,R0
RTS PC
;Program initialization
START: MOV #SPSTRT,SP ;Set up stack???
ALUN$S #1,#"TI,#0 ;LUN 1 is TI: device
BCC 1$
IOT ;Punt if error
1$: QIOW$S #IO.ATT,#1,#1 ;Attach it
BCC 2$
IOT ;Punt if error
2$: QIOW$S #SF.GMC,#1,#1,,,,<#STATBF,#2> ;See if we're talking to 10 or 11
BCC 3$
IOT ;Punt if error
3$: TSTB TALK11 ;Are we talking to the 11?
BNE 4$ ; Yes
JMP WRTADR ; No - go tell 10 our memory addresses
4$: QIOW$S #IO.WLB,#1,#1,,#WRSTS,,<#HIMES,#HISIZ,#0> ;Say hello
BCC 5$
IOT ;Punt if error
5$: MOV #3,LUN10 ;Use logical unit number 3 to talk to 10
ALUN$S #3,#"TT,#10 ;LUN 3 is device TT10:
QIOW$S #IO.ATT,#3,#1 ;Attach it
BCC 6$
IOT ;Punt if error
6$: MOVB #1,ECHOP ;Turn off echoing
QIOW$S #SF.SMC,#3,#1,,,,<#ECHO,#2>
BCC 7$
IOT ;Punt if error
7$: MOVB #1,SLAVEP ;Enslave terminal
QIOW$S #SF.SMC,#3,#1,,,,<#SLAVE,#2>
BCC 8$
IOT ;Punt if error
8$: QIOW$S #IO.WLB,#3,#1,,#WRSTS,,<#LOGMES,#LOGSIZ,#0> ;Login on 10
BCC 9$
IOT ;Punt if error
9$: MOV #3,R3
JSR PC,GETLIN ;Get a line from 10
CMP R4,#2
BNE 9$
CMPB (R1)+,#"↑ ;Look for "↑C"
BNE 9$
CMPB (R1),#"C
BNE 9$
QIOW$S #IO.WLB,#3,#1,,#WRSTS,,<#RUNMES,#RUNSIZ,#0> ;Start 11FTP program
BCC 10$
IOT ;Punt if error
10$: MOV #3,R3
JSR PC,GETLIN ;Get echoed line from 10
WRTADR: GREG$S ,#REGBUF ;Get region base address
BCC 1$
IOT
1$: MOV REGBUF,R1
JSR PC,OUTNUM ;Print it out
MOV #BUFPTR,R1 ;Give local address of buffer pointer
JSR PC,OUTNUM ;Print it out
TSTB TALK11 ;See who's in charge
BEQ 2$ ;If 10 skip ahead
MOV #3,R3 ;If 11 read back the echoed lines
JSR PC,GETLIN ; mapping offset for region base
JSR PC,GETLIN ; & buffer pointer
2$: ALUN$S #2,#"SY,#0 ;LUN 2 is SY: by default
FINIT$
BCC CLOOP
IOT
;Command loop
CLOOP: CLR BUFPTR
CLR FILDON
CLR DEVCNT ;Re-initialize Data set descriptor
CLR UICCNT
CLR FILCNT
TSTB TALK11 ;Talking to 11?
BEQ 1$ ; No
QIOW$S #IO.WLB,#1,#1,,#WRSTS,,<#PROMPT,#PRSIZ,#0> ;Type out prompt
1$: MOV #1,R3 ;Get a command line from TI:
JSR PC,GETLIN
CMPB (R1),#"E ;All done? Command = "E"
BNE 2$ ; No - go execute command
TSTB TALK11 ;Did it come from the 10?
BNE 2$ ; No - ignore it
EXIT$S ERROR ; Yes - Go away
2$: MOV RDCNT,R4 ;See how many characters were typed
BEQ 1$ ;Ignore null lines
MOVB (R1)+,CMD ;Save command
DEC R4 ;Update char count
JSR PC,SKIPB ;Skip over blanks
MOV R1,F1 ;f1 ← first part of string
3$: CMPB (R1)+,#"← ;find "←" if present
BEQ 4$
DEC R4 ;Update char count
BGT 3$ ; & Keep looking
4$: MOV R1,F1+2
SUB F1,F1+2
DEC F1+2 ;Compute length of file spec
INC R1 ;Skip past "←"
DEC R4 ;Update char count
JSR PC,SKIPB ;Skip over blanks
MOV R1,F2 ;f2 ← rest of string
MOV R4,F2+2
CMDDIS: BIC #40,CMD ;Make command upper case
CMPB CMD,#"S ;See what we're supposed to do
BNE 1$
JMP RDFILE ;"S" - Go read in an old file
1$: CMPB CMD,#"G
BNE 2$
JMP WTFILE ;"G" - Go write out a new file
2$: CMPB CMD,#"A
BNE 3$
JMP SETPPN ;"A" - Set alias ppn for 10
3$: CMPB CMD,#"X
BNE 4$
JMP DONE ;"X" - Time to go away
4$: QIOW$S #IO.WLB,#1,#1,,#WRSTS,,<#UNKMES,#UNKSIZ,#40> ;Bad command
JMP CLOOP
;Store 10file ← 11file
RDFILE: TSTB TALK11 ;See who we're talking to
BEQ 5$ ;If 10 skip ahead
MOV #F1,R0
JSR PC,FPAR10 ;PARSE10(f1)
MOV #F2,R0
JSR PC,FPAR11 ;PARSE11(f2)
BCC 1$ ;Check for bad device
JMP CLOOP ; Yup - punt
1$: TST FNAM10+2 ;Is fnam10 = null?
BNE 2$ ; No
MOV FNAM11,FNAM10 ; Yes: fnam10 ← fnam11
MOV FNAM11+2,FNAM10+2
2$: TST FEXT10+2 ;Is fext10 = null?
BNE 3$ ; No
MOV FEXT11,FEXT10 ; Yes: fext10 ← fext11
MOV FEXT11+2,FEXT10+2
3$: TST FNAM11+2 ;Is fnam11 = null?
BNE 4$ ; No
MOV FNAM10,FNAM11 ; Yes: fnam11 ← fnam10
MOV FNAM10+2,FNAM11+2
4$: TST FEXT11+2 ;Is fext11 = null?
BNE 6$ ; No
MOV FEXT10,FEXT11 ; Yes: fext11 ← fext10
MOV FEXT10+2,FEXT11+2
BR 6$
5$: MOV #F1,R0
JSR PC,FPAR11 ;PARSE11(f1)
BCC 6$ ;Check for bad device
JMP CLOOP ; Yup - punt
6$: JSR PC,SETF11 ;Copy file name so it's one string
OPEN$R #FDB,#2,#DATSET,#FD.RWM,#DBUF,#512.,FILERR ;Try to open it
TSTB TALK11 ;Talking to 11?
BEQ 10$ ; No
MOVB #"G ,CMDMES
JSR PC,SETF10 ;Tell 10 name of file to create
BCC 11$ ;Go do the transfer if 10 said OK
JMP CLOOP ;Else punt
10$: QIOW$S #IO.WLB,#1,#1,,#WRSTS,,<#OKMES,#OKSIZ,#40> ;Tell 10 all's well
BCC 11$
IOT ;Punt if error
11$: MOV FDB+F.EFBK+2,R4 ;R4 has count of blocks in file
RLOOP: READ$ #FDB,,,,,,,RWERR ;Read in next block
WAIT$ #FDB,,,RWERR
TSTB IOSTAT ;Did it succeed?
BPL 1$ ; Yes
JMP RWERR ; No - punt
1$: DEC R4 ;One less block to read
BGT 2$ ;Was this the last block?
MOV F.FFBY(R0),FILDON ; Yes - tell 10 this is the end
2$: MOV #DBUF,BUFPTR ;Give buffer to 10
3$: MRKT$S #1,#2,#1 ;Wait two ticks
BCS 4$ ;Make sure we got scheduled
WTSE$S #1
4$: TST BUFPTR ;Has 10 finished with it yet?
BNE 3$ ; No - keep waiting
TST R4 ;More to send?
BGT RLOOP ; Yup - go read next block
JMP FDONE ; No - go close file & get next command
;Get 11file ← 10file
WTFILE: MOV #F1,R0
JSR PC,FPAR11 ;PARSE11(f1)
BCC 1$ ;Check for bad device
JMP CLOOP ; Yup - punt
1$: MOV #F2,R0
JSR PC,FPAR10 ;PARSE10(f2)
TST FNAM11+2 ;Is fnam11 = null?
BNE 2$ ; No
MOV FNAM10,FNAM11 ; Yes: fnam11 ← fnam10
MOV FNAM10+2,FNAM11+2
2$: TST FEXT11+2 ;Is fext11 = null?
BNE 3$ ; No
MOV FEXT10,FEXT11 ; Yes: fext11 ← fext10
MOV FEXT10+2,FEXT11+2
3$: TST FNAM10+2 ;Is fnam10 = null?
BNE 4$ ; No
MOV FNAM11,FNAM10 ; Yes: fnam10 ← fnam11
MOV FNAM11+2,FNAM10+2
4$: TST FEXT10+2 ;Is fext10 = null?
BNE 5$ ; No
MOV FEXT11,FEXT10 ; Yes: fext10 ← fext11
MOV FEXT11+2,FEXT10+2
5$: JSR PC,SETF11 ;Copy file name so it's one string
OPEN$W #FDB,#2,#DATSET,#FD.RWM,#DBUF,#512.,FILERR ;Try to enter it
TSTB TALK11 ;Talking to 11?
BEQ 10$ ; No
MOVB #"S ,CMDMES
JSR PC,SETF10 ;Tell 10 name of file to read
BCC 11$ ;Go do the transfer if 10 said OK
JMP CLOOP ;Else punt
10$: QIOW$S #IO.WLB,#1,#1,,#WRSTS,,<#OKMES,#OKSIZ,#40> ;Tell 10 all's well
BCC 11$
IOT ;Punt if error
11$: CLR R4 ;Keep a count of # of blocks we write
WLOOP: MOV #DBUF,BUFPTR ;Tell 10 where to stick block
1$: MRKT$S #1,#2,#1 ;Wait two ticks
BCS 2$ ;Make sure we got scheduled
WTSE$S #1
2$: TST BUFPTR ;Has 10 finished with it yet?
BNE 1$ ; No - keep waiting
WRITE$ #FDB,,,,,,,RWERR ;Write out next block
WAIT$ #FDB,,,RWERR
TSTB IOSTAT ;Did it succeed?
BMI RWERR ; No - punt
INC R4 ;Update block count
TST FILDON ;Was this last block?
BEQ WLOOP ; No - get next block
; Yes - fix up FDB
MOVB #2,F.RTYP+FDB ;Say we're really a variable length file
MOVB #2,F.RATT+FDB ;Say to print a cr after each record
MOV #130.,F.RSIZ+FDB ;Biggest record should be less than this
MOV R4,F.EFBK+2+FDB ;Tell how many blocks we are
MOV FILDON,F.FFBY+FDB ;Tell where the last record ends
;Now we can close the file
FDONE: CLOSE$ #FDB,ERROR ;All done with file now
CLR BUFPTR
JMP CLOOP ;Get next command
FILERR: QIOW$S #IO.WLB,#1,#1,,#WRSTS,,<#BADFIL,#BFILSZ,#40> ;Abort if bad file
BCC 1$
IOT ;Punt if error
1$: JMP CLOOP ;Try again
RWERR: MOV #1,BUFPTR ;Abort if read/write error
JMP CLOOP ;Try again
ERROR: IOT ;Punt if error
;Set alias ppn for 10 & Exit
SETPPN: MOV #F1,R0
JSR PC,FPAR10 ;Go parse ppn
MOV PPN10,R1 ;Get string to copy
MOV PPN10+2,R4 ; & its length
MOV #DEFPPN,R2 ;Where to copy it to
MOV R4,ALIAS+2 ;Update ppn length
1$: MOVB (R1)+,(R2)+ ;Copy chars
SOB R4,1$
JMP CLOOP ;Done
DONE: TSTB TALK11 ;Are we in charge?
BEQ 5$ ; No - just go away
QIOW$S #IO.WLB,#3,#1,,#WRSTS,,<#BYEMES,#BYESIZ,#0> ;Tell 10 goodbye
BCC 1$
IOT ;Punt if error
1$: ;flush buffer?
2$: CLRB ECHOP ;Turn echoing back on
CLRB SLAVEP ;Become a free terminal again
QIOW$S #SF.SMC,#3,#1,,,,<#ECHO,#6>
BCC 5$
IOT ;Punt if error
5$: EXIT$S ERROR ;Go away
.END START